package com.zhuangxiaoyan.designpattern.factorymodel;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * @Classname FactoryDemo
 * @Description TODO
 * @Date 2022/3/26 10:58
 * @Created by xjl
 */
public class FactoryDemo {
}

abstract class Pizza {
    protected String name;

    public void setName(String name) {
        this.name = name;
    }

    public abstract void prepare();

    public void bake() {
        System.out.println(name + " baking...");
    }

    public void cut() {
        System.out.println(name + " cutting...");
    }

    public void box() {
        System.out.println(name + " boxing...");
    }
}

//希腊风味披萨
class GreekPizza extends Pizza {
    @Override
    public void prepare() {
        setName("GreekPizza");
        System.out.println(name + " preparing...");
    }
}

// 奶酪披萨
class CheesePizza extends Pizza {
    @Override
    public void prepare() {
        setName("CheesePizza");
        System.out.println(name + " preparing...");
    }
}

// 胡椒披萨
class PepperPizza extends Pizza {
    @Override
    public void prepare() {
        setName("PepperPizza");
        System.out.println(name + " preparing...");
    }
}

class PizzaFactory {
    /**
     * @description 简单工厂模式原理
     * @param: null
     * @date: 2022/3/26 11:01
     * @return:
     * @author: xjl
     */
    public Pizza createPizza(String orderType) {
        Pizza pizza = null;
        switch (orderType) {
            case "cheese":
                pizza = new CheesePizza();
                break;
            case "greek":
                pizza = new GreekPizza();
                break;
            case "pepper":
                pizza = new PepperPizza();
                break;
            default:
                break;
        }
        return pizza;
    }

    /**
     * @description 静态工厂模式也是简单工厂模式的一种，只是将工厂方法改为静态方法
     * @param: orderType
     * @date: 2022/3/26 11:04
     * @return: com.zhuangxiaoyan.designpattern.factorymodel.Pizza
     * @author: xjl
     */
    public static Pizza createPizzaV2(String orderType) {
        Pizza pizza = null;
        switch (orderType) {
            case "cheese":
                pizza = new CheesePizza();
                break;
            case "greek":
                pizza = new GreekPizza();
                break;
            case "pepper":
                pizza = new PepperPizza();
                break;
            default:
                break;
        }
        return pizza;
    }
}

class OrderPizza {
    public OrderPizza() {
        Pizza pizza = null;
        String orderType;
        do {
            orderType = getType();
            if ("cheese".equals(orderType)) {
                pizza = new CheesePizza();
            } else if ("greek".equals(orderType)) {
                pizza = new GreekPizza();
            } else if ("pepper".equals(orderType)) {
                pizza = new PepperPizza();
            } else {
                System.out.println("输入类型错误，程序退出");
                break;
            }
            pizza.prepare();
            pizza.bake();
            pizza.cut();
            pizza.box();
        } while (true);
    }

    private String getType() {
        System.out.println("请输入披萨类型：");
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        try {
            return reader.readLine();
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }
}

/**
 * @description 简单工厂模式的调用
 * @param: null
 * @date: 2022/3/26 11:01
 * @return:
 * @author: xjl
 */
class OrderPizzaV2 {
    private PizzaFactory pizzaFactory;

    public OrderPizzaV2(PizzaFactory pizzaFactory) {
        this.pizzaFactory = pizzaFactory;
        orderPizza();
    }

    private String getType() {
        System.out.println("请输入披萨类型：");
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        try {
            return reader.readLine();
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }

    public void orderPizza() {
        Pizza pizza = null;
        do {
            pizza = pizzaFactory.createPizza(getType());
            if (pizza == null) {
                System.out.println("Failed to Order Pizza");
            } else {
                pizza.prepare();
                pizza.bake();
                pizza.cut();
                pizza.box();
            }
        } while (true);
    }
}

// 奶酪披萨
class LDCheesePizza extends Pizza {
    @Override
    public void prepare() {
        setName("CheesePizza");
        System.out.println(name + " preparing...");
    }
}

// 胡椒披萨
class LDPepperPizza extends Pizza {
    @Override
    public void prepare() {
        setName("PepperPizza");
        System.out.println(name + " preparing...");
    }
}

// 奶酪披萨
class BJCheesePizza extends Pizza {
    @Override
    public void prepare() {
        setName("CheesePizza");
        System.out.println(name + " preparing...");
    }
}

// 胡椒披萨
class BJPepperPizza extends Pizza {
    @Override
    public void prepare() {
        setName("PepperPizza");
        System.out.println(name + " preparing...");
    }
}

/**
 * @description 工厂模板方式
 * @param: null
 * @date: 2022/3/26 11:19
 * @return:
 * @author: xjl
 */
abstract class OrderPizzaV3 {

    public void orderPizza() {
        Pizza pizza = null;
        do {
            pizza = createPizza(getType());
            if (pizza == null) {
                System.out.println("Failed to Order Pizza");
            } else {
                pizza.prepare();
                pizza.bake();
                pizza.cut();
                pizza.box();
            }
        } while (true);
    }

    public abstract Pizza createPizza(String orderType);

    private String getType() {
        System.out.println("请输入披萨类型：");
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        try {
            return reader.readLine();
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }
}

class LDOrderPizza extends OrderPizzaV3 {
    /**
     * @description 重写方法
     * @param: orderType
     * @date: 2022/3/26 11:20
     * @return: com.zhuangxiaoyan.designpattern.factorymodel.Pizza
     * @author: xjl
     */
    @Override
    public Pizza createPizza(String orderType) {
        Pizza pizza = null;
        switch (orderType) {
            case "cheese":
                pizza = new LDCheesePizza();
                break;
            case "pepper":
                pizza = new LDPepperPizza();
                break;
            default:
                break;
        }
        return pizza;
    }
}

class BJOrderPizza extends OrderPizzaV3 {
    /**
     * @description 重写方法
     * @param: orderType
     * @date: 2022/3/26 11:20
     * @return: com.zhuangxiaoyan.designpattern.factorymodel.Pizza
     * @author: xjl
     */
    @Override
    public Pizza createPizza(String orderType) {
        Pizza pizza = null;
        switch (orderType) {
            case "cheese":
                pizza = new BJCheesePizza();
                break;
            case "pepper":
                pizza = new BJPepperPizza();
                break;
            default:
                break;
        }
        return pizza;
    }
}

/**
 * @description 抽象工厂类
  * @param: null
 * @date: 2022/3/26 11:23
 * @return:
 * @author: xjl
*/
interface AbsPizzaFactory {
    Pizza createPizza(String orderType);
}

/**
 * @description 实现抽象工厂类实现抽象方法，与工厂方法不同，工厂方法
  * @param: null
 * @date: 2022/3/26 11:23
 * @return:
 * @author: xjl
*/
class BJPizzaFactory implements AbsPizzaFactory {
    @Override
    public Pizza createPizza(String orderType) {
        Pizza pizza = null;
        switch (orderType) {
            case "cheese":
                pizza = new BJCheesePizza();
                break;
            case "pepper":
                pizza = new BJPepperPizza();
                break;
            default:
                break;
        }
        return pizza;
    }
}

class LDPizzaFactory implements AbsPizzaFactory {
    @Override
    public Pizza createPizza(String orderType) {
        Pizza pizza = null;
        switch (orderType) {
            case "cheese":
                pizza = new LDCheesePizza();
                break;
            case "pepper":
                pizza = new LDPepperPizza();
                break;
            default:
                break;
        }
        return pizza;
    }
}